---
title: "Discover & Run Agent"
description: "How to discover and run ACP agents via REST and Python SDK"
---

This guide shows how to discover available ACP agents and execute them using different modes (synchronous, asynchronous, and streaming) through both REST API and Python SDK.

## Discover available agents

Before running agents, you need to know what's available. ACP servers expose agent metadata through a discovery endpoint that lists all registered agents with their capabilities. Use REST for simple interactions or Python SDK for richer, programmatic control.

### Using REST API

Send a GET request to the `/agents` endpoint to list available agents:

<CodeGroup>
```bash Request
curl http://localhost:8000/agents
```

```json Response
{
  "agents": [
    { "name": "echo", "description": "Echoes everything", "metadata": {} }
  ]
}
```

</CodeGroup>

### Using Python SDK
For programmatic access, use the Python client to discover agents:

```python
import asyncio
from acp_sdk.client import Client

async def list_agents():
    async with Client(base_url="http://localhost:8000") as client:
        async for agent in client.agents():
            print(agent)

if __name__ == "__main__":
    asyncio.run(list_agents())
```

<Note>For discovering agents across multiple servers, consider using a service registry or the [BeeAI Platform](https://beeai.dev) for centralized agent discovery.</Note>

## Run an agent
ACP supports three execution modes, each suited for different use cases:
- **Synchronous**: Best for quick operations where you need immediate results
- **Asynchronous**: Ideal for long-running tasks that you can check later
- **Streaming**: Perfect for real-time applications requiring incremental updates

### Message Format
All agent interactions use a standardized message format:

```bash
{
  "role": "user",
  "parts": [
    {
      "content_type": "text/plain",
      "content": "Your message here"
    }
  ]
}
```
Learn more about [Message Stucture](/core-concepts/message-structure).

### Synchronous execution

Synchronous execution blocks until the agent completes processing and returns the full response.
<CodeGroup>
```bash Request
curl -X POST http://localhost:8000/runs \
  -H "Content-Type: application/json" \
  -d '{
        "agent_name": "echo",
        "input": [{"role": "user", "parts": [{"content": "Hello"}]}],
        "mode": "sync"
      }'
```

```json Response
{
  "agent_name": "echo",
  "status": "completed",
  "output": [
    { 
      "role": "agent/echo",
      "parts": [{ "content_type": "text/plain", "content": "Hello" }] 
    }
  ]
}
```

</CodeGroup>

Using Python SDK:

```python
import asyncio
from acp_sdk.client import Client
from acp_sdk.models import Message, MessagePart

async def run_sync():
    async with Client(base_url="http://localhost:8000") as client:
        run = await client.run_sync(
            agent="echo",
            input=[Message(parts=[MessagePart(content="Hello")])]
        )
        print(run.output)

if __name__ == "__main__":
    asyncio.run(run_sync())
```

### Asynchronous execution

Asynchronous execution returns immediately with a run ID that you can use to check status and retrieve (poll) results later.


Start async execution:

<CodeGroup>

```bash Request
curl -X POST http://localhost:8000/runs \
  -H "Content-Type: application/json" \
  -d '{
        "agent_name": "echo",
        "input": [{"role": "user", "parts": [{"content": "Hello"}]}],
        "mode": "async"
      }'
```

```json Response
{
  "agent_name": "echo",
  "status": "created",
  "run_id": "12345678-abcd-1234-abcd-123456789abc"
}
```

</CodeGroup>

Check the status/result using the returned `run_id`:

```bash
curl http://localhost:8000/runs/<run_id>
```

Using Python SDK:

```python
import asyncio
from acp_sdk.client import Client
from acp_sdk.models import Message, MessagePart

async def run_async():
    async with Client(base_url="http://localhost:8000") as client:
        run = await client.run_async(
            agent="echo",
            input=[Message(parts=[MessagePart(content="Hello")])]
        )
        print("Run ID:", run.run_id)

        # Later, retrieve results
        result = await client.run_status(run_id=run.run_id)
        print(result)

if __name__ == "__main__":
    asyncio.run(run_async())
```

### Streaming execution

Streaming execution provides real-time updates using Server-Sent Events (SSE). Ideal for applications that need to show progress or partial results as they're generated.

```bash
curl -N -H "Accept: text/event-stream" -X POST http://localhost:8000/runs \
  -H "Content-Type: application/json" \
  -d '{
        "agent_name": "echo",
        "input": [{"role": "user", "parts": [{"content": "Hello"}]}],
        "mode": "stream"
      }'
```

Using Python SDK:

```python
import asyncio
from acp_sdk.client import Client
from acp_sdk.models import Message, MessagePart

async def run_stream():
    async with Client(base_url="http://localhost:8000") as client:
        async for event in client.run_stream(
            agent="echo",
            input=[Message(parts=[MessagePart(content="Hello")])]
        ):
            print(event)

if __name__ == "__main__":
    asyncio.run(run_stream())
```
